package com.zhang.common.util.object;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * 工具类实体类转换带有下划线的数据库字段名
 * 数据库字段映射
 */
public class EntityHelper {

    public static final Logger logger = LoggerFactory.getLogger(EntityHelper.class);

    /**
     * 获取Bean对应的数据库字段
     *
     * @param object
     * @return
     */
    public static String getFields(Class object) {
        StringBuffer sql = new StringBuffer();
        Field[] fields = object.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            String name = field.getName();
            String str = convertField(name);
            if (i != fields.length - 1) {
                sql.append(str).append(",");
            } else {
                sql.append(str);
            }
        }
        return sql.toString();
    }

    /**
     * 对象字段转数据库字段
     *
     * @param name
     * @return
     */
    public static String convertField(String name) {
        Pattern pattern = compile("[A-Z]");
        Matcher matcher = pattern.matcher(name);
        while (matcher.find()) {
            String old = matcher.group();
            String ne = matcher.group().toLowerCase();
            name = name.replaceAll(old, "_" + ne);
        }
        return name;
    }

    /**
     * 数据库结果集映射到Bean
     *
     * @param rs
     * @param className
     * @return
     */
    public static Object convertToBean(ResultSet rs, Class className) {
        Object nt = null;
        Field[] fields = className.getDeclaredFields();
        try {
            nt = className.newInstance();
            for (Field field : fields) {
                //如果结果中没有改field项则跳过
                String name = field.getName();
                String str = convertField(name);
                try {
                    rs.findColumn(str);
                } catch (Exception e) {
                    continue;
                }
                //修改相应filed的权限
                boolean accessFlag = field.isAccessible();
                field.setAccessible(true);
                setFieldValue(nt, field, rs, str);
                //恢复相应field的权限
                field.setAccessible(accessFlag);
            }
        } catch (Exception e) {
            logger.error("数据集转换javaBean异常");
            return null;
        }
        return nt;
    }

    private static void setFieldValue(Object obj, Field field, ResultSet rs, String columnName) throws SQLException, IllegalAccessException {
        Class<?> fieldClazz = field.getType();
        if (fieldClazz == int.class || fieldClazz == Integer.class) {
            field.set(obj, rs.getInt(columnName));
        } else if (fieldClazz == boolean.class || fieldClazz == Boolean.class) {
            field.set(obj, rs.getBoolean(columnName));
        } else if (fieldClazz == String.class) {
            field.set(obj, rs.getString(columnName));
        } else if (fieldClazz == float.class) {
            field.set(obj, rs.getFloat(columnName));
        } else if (fieldClazz == double.class || fieldClazz == Double.class) {
            field.set(obj, rs.getDouble(columnName));
        } else if (fieldClazz == BigDecimal.class) {
            field.set(obj, rs.getBigDecimal(columnName));
        } else if (fieldClazz == short.class || fieldClazz == Short.class) {
            field.set(obj, rs.getShort(columnName));
        } else if (fieldClazz == Date.class) {
            field.set(obj, rs.getDate(columnName));
        } else if (fieldClazz == Timestamp.class) {
            field.set(obj, rs.getTimestamp(columnName));
        } else if (fieldClazz == Long.class || fieldClazz == long.class) {
            field.set(obj, rs.getLong(columnName));
        } else if (fieldClazz == Byte.class || fieldClazz == byte.class) {
            field.set(obj, rs.getByte(columnName));
        }
    }
}
